using System;
using System.Xml;

using TaskLib;

namespace TaskService
{
    /// <summary>
    /// Windows Service application for creating and monitoring the tasks
    /// </summary>
    public class Service : System.ServiceProcess.ServiceBase
    {
        #region System Generated Code

        /// <summary> 
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container _components;


        /// <summary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            ServiceName = Properties.Resources.Service_ServiceName;
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Service"/> class.
        /// </summary>
        public Service()
        {
            // This call is required by the Windows.Forms Component Designer.
            InitializeComponent();

            createEventLog();

            loadConfiguration();

        }

        #endregion

        #region Destructors

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_components != null)
                {
                    _components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        #endregion

        #region Private Variables

        private TaskServiceConfig _config;
        private TaskPoller _taskPoller;

        // Other Variables
        private readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private System.Diagnostics.EventLog _eLog;

        #region Private Constants

        #endregion Private Constants

        #region Private Enums

        #endregion Private Enums

        #endregion Private Variables

        // The main entry point for the process
        static void Main()
        {
            System.ServiceProcess.ServiceBase[] servicesToRun;
            servicesToRun = new System.ServiceProcess.ServiceBase[] { new Service() };
            Run(servicesToRun);
        }

        #region Public Methods

        #region OnStart

        /// <summary>
        /// Set things in motion so your service can do its work.
        /// </summary>
        protected override void OnStart(string[] args)
        {
            eventLogIt(Properties.Resources.ServiceStarting);
            _log.Debug(Properties.Resources.ServiceStarting);

            try
            {
                _log.DebugFormat(Properties.Resources.PluginPath, _config.PluginPath);

                _taskPoller = new TaskPoller(_config.PluginPath);
                _taskPoller.Start();

                _log.Debug(Properties.Resources.ServiceStarted);
                eventLogIt(Properties.Resources.ServiceStarted);
            }
            catch (Exception ex)
            {
                _log.Debug(string.Format(Properties.Resources.ServiceFailedToStart, ex), ex);
                eventLogIt(string.Format(Properties.Resources.ServiceFailedToStart, ex), System.Diagnostics.EventLogEntryType.Error);
            }

            

        }

        #endregion OnStart

        #region OnStop
        /// <summary>
        /// Stop this service.
        /// </summary>
        protected override void OnStop()
        {
            eventLogIt(Properties.Resources.ServiceStopping);
            _log.Debug(Properties.Resources.ServiceStopping);

            try
            {
                _taskPoller.Shutdown();
                _log.Debug(Properties.Resources.ServiceStopped);
                eventLogIt(Properties.Resources.ServiceStopped);
            }
            catch (Exception ex)
            {
                _log.Debug(string.Format(Properties.Resources.ServiceFailedToStop, ex), ex);
                eventLogIt(string.Format(Properties.Resources.ServiceFailedToStop, ex), System.Diagnostics.EventLogEntryType.Error);
            }
            
        }

        #endregion OnStop

        #endregion Public Methods

        #region Helper Functions

        #region loadConfiguration
        /// <summary>
        /// Loads the configuration.
        /// </summary>
        private void loadConfiguration()
        {
            string configFile = System.Reflection.Assembly.GetExecutingAssembly().Location + ".Settings.xml";
            
            eventLogIt(string.Format(Properties.Resources.ConfigurationAttemptLoad, configFile));

            try
            {
                _config = new TaskServiceConfig(null, configFile);

                if (!string.IsNullOrEmpty(_config.Log4NetConfig))
                {
                    XmlDocument xml = new XmlDocument();
                    xml.LoadXml(_config.Log4NetConfig);
                    log4net.Config.XmlConfigurator.Configure(xml.DocumentElement);
                }
            }
            catch (Exception ex)
            {
                eventLogIt(string.Format(Properties.Resources.ConfigurationException, ex), System.Diagnostics.EventLogEntryType.Error);
            }

            _log.Debug(Properties.Resources.ConfigurationLoaded);
        }
        #endregion loadConfiguration

        #region createEventLog

        /// <summary>
        /// Creates a Event Log object to track issues with the loading of the Service.
        /// </summary>
        /// <remarks>
        /// This is required in case anything goes wrong with the application prior to it fully
        /// loading the configuration and the custom log4net configuration kicks in.<br></br>
        /// Somethings that can go wrong<br></br>
        /// <ul>
        /// <li><see cref="TaskService"/>.<c>Exe</c>.Settings.xml is not found.</li>
        /// <li>The configuration file malformed.</li>
        /// </ul>
        /// </remarks>
        private void createEventLog()
        {
            _eLog = new System.Diagnostics.EventLog();
            _eLog.Source = Properties.Resources.Service_DisplayName;
            _eLog.Log = "Application";
        }

        #endregion createEventLog

        #region eventLogIt

        private void eventLogIt(string msg)
        {
            eventLogIt(msg, System.Diagnostics.EventLogEntryType.Information);
        }

        private void eventLogIt(string msg, System.Diagnostics.EventLogEntryType eleType)
        {
            _eLog.WriteEntry(msg, eleType);
            Console.WriteLine(msg);
        }

        #endregion eventLogIt

        #endregion Helper Functions
    }
}